home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DNet.more / DPOP.cp next >
Encoding:
Text File  |  1996-07-05  |  7.5 KB  |  359 lines  |  [TEXT/R*ch]

  1. // UPOP.cp 
  2. // POP Mail reader
  3. //by D. Gilbert, May 1991
  4.  
  5.  
  6.             
  7. /*  ---   general use: ------------
  8.         TPOP        VAR  aPop;
  9.         
  10.         New(aPop); 
  11.         FailNIL(aPop);
  12.         aPop->IPOP( 'cricket.bio.indiana.edu', 'anybody', 'somepass');
  13.         
  14.         Repeat as requested from User commands:
  15.         if aPop.MailWaiting then begin
  16.             nMsg= aPop->NumberOfMessages();
  17.             for iMsg= 1 to nMsg do begin
  18.                 hMsg= aPop->ReadTop( iMsg, 0);
  19.                 --- collect, display msg directory ----
  20.                 end();
  21.                 
  22.             -- user select msg to read --
  23.             hMsg= aPop->ReadMail( iMsg, True); 
  24.             
  25.             aPop->Release(); -- when done reading for now
  26.             end();
  27.                         
  28.         aPop->Free();  -- when entirely done with mail
  29. */
  30.  
  31. #include "includes.h"
  32. #include "UTCP.h"
  33. #include "UPOP.h"
  34.  
  35. #pragma segment UPOP
  36.  
  37.  
  38. const short        kPOPport = 110; // telnet port 110 == POP3 
  39.  
  40. //const int        kTCPwaitingforopen = 64;
  41. const int        kPOPopen = 128;        // fPOPstates 
  42. const int        kPOPclosed = 256;
  43. const int        kPOPtransaction = 512;
  44.  
  45. const char        chLineFeed    = 10;
  46. const char        chRtn                = 13; 
  47.     
  48.     
  49.  
  50.  
  51. TPOP::TPOP( const CStr255& POPAddress, const CStr63& password)
  52. {
  53.     //ITCP();
  54.     fPOPState= kPOPclosed;
  55.     fPopAddress= POPAddress;
  56.     fPassword= password;  
  57. //-    ResetHost( POPaddress, password); << NEED InstallMessageLine before this 
  58. }
  59.  
  60. TPOP::TPOP()
  61. {
  62.     fPOPState= kPOPclosed;
  63.     fPopAddress= "";
  64.     fPassword= "";  
  65. }
  66.             
  67. TPOP::~TPOP()   
  68. {
  69.     Release();
  70. }
  71.  
  72.  
  73.  
  74.  
  75. void TPOP::ResetHost( const CStr255& POPAddress, const CStr63& password)
  76. {
  77.     fPopAddress= POPAddress;
  78.     fPassword= password; //save for .ReOpen 
  79.     ReOpen();
  80. }
  81.  
  82. void TPOP::ReOpen()
  83. {
  84.     Handle        hMsg; 
  85.     CStr255        aHost, aName;
  86.     short         k;
  87.      
  88.     k= fPopAddress.Pos("@");
  89.     if (k==0) Fail("Bad POP mail address, missing '@'");
  90.     aName= fPopAddress;
  91.     aName[0]=  k-1;
  92.     aHost= fPopAddress;
  93.     aHost.Delete(1,k);
  94.     
  95.     // ?? make sure we are closed 
  96.     if (Status() != kTCPreleased)  this->Release();
  97.     
  98.   this->ShowMessage( aHost);
  99.     fPOPState= kPOPclosed;
  100.     fMsgCount= 0;
  101.     fPOPhostIP= this->NameToAddress( aHost);
  102.   if (fPOPhostIP == 0) Fail("Bad address for POP Host.");
  103.     else {
  104.         ActiveOpen(fPOPhostIP, kPOPport, 0);
  105.         if (Failed()) return;
  106.         if (!WaitedForOpen()) return;
  107.         fPOPState= kPOPopen;
  108.         DisposeIfHandle( RecvChars( CharsAvailable()));    
  109.  
  110.         SendStr("USER " + aName, kAddCRLF);
  111.         hMsg= RecvUpTo( true, chLineFeed, NULL);
  112.         this->ShowMessage( (char *) (*hMsg));
  113.         DisposeIfHandle( RecvChars( CharsAvailable()));
  114.         
  115.         if (**hMsg != '+') 
  116.             Fail( CStr63("Bad username for POP: ") + (char *)(*hMsg) );
  117.         else {
  118.             DisposeIfHandle( hMsg);
  119.             SendStr( "PASS " + fPassword, kAddCRLF);
  120.             hMsg= RecvUpTo( true, chLineFeed, NULL);
  121.             aName= CStr255( (char *)(*hMsg));
  122.             this->ShowMessage( aName);
  123.             DisposeIfHandle( hMsg);
  124.             DisposeIfHandle( RecvChars( CharsAvailable()));
  125.             if (aName[1] != '+') 
  126.                 Fail( "Bad password for POP: "+ aName);
  127.             else {
  128.                 fPOPState= kPOPtransaction;
  129.                 GetMessageCount();
  130.                 }
  131.             }
  132.         DisposeIfHandle( hMsg);
  133.         }
  134. //- this->ShowMessage( State); 
  135. }
  136.  
  137.  
  138. void TPOP::Close() // override 
  139. {
  140.     FailInfo fi;
  141.     if (fi.Try()) {
  142.         if (fPOPState != kPOPclosed) {
  143.             SendStr("QUIT", kAddCRLF);
  144.             fTimeout= 240;
  145.             EatResponseLine();
  146.             fTimeout= gTCPTimeout;
  147.             fPOPState= kPOPclosed;
  148.             }
  149.         TTCP::Close();
  150.         fi.Success();
  151.         }
  152.     else { // fail
  153.         TTCP::Close();
  154.         fi.ReSignal();
  155.         }
  156. }
  157.  
  158. void TPOP::Release() // override 
  159. {
  160.     FailInfo fi;
  161.     if (fi.Try()) {
  162.         if (fPOPState != kPOPclosed) {
  163.             SendStr("QUIT", kAddCRLF);
  164.             fTimeout= 240;
  165.             EatResponseLine();
  166.             fTimeout= gTCPTimeout;
  167.             fPOPState= kPOPclosed;
  168.             }
  169.         TTCP::Release();
  170.         fi.Success();
  171.         }
  172.     else { // fail
  173.         TTCP::Release();
  174.         fi.ReSignal();
  175.         }
  176. }
  177.  
  178.  
  179.  
  180.             
  181. char* TPOP::StatusString(short state)   // override  
  182. {
  183.     CStr255 aState;
  184.     aState= TTCP::StatusString(state);
  185.     switch (fPOPState) {
  186.         case kPOPclosed    : aState=  aState + "; POP closed"; break;
  187.         case kPOPopen        : aState= aState +"; POP connected"; break;
  188.         case kPOPtransaction    : aState= aState +"; POP mailbox open"; break;
  189.         }
  190.     return (char*) aState;
  191. }
  192.  
  193.  
  194. void TPOP::GetMessageCount()
  195.     fMsgCount= 0;
  196.     if (fPOPState == kPOPtransaction) {
  197.         SendStr("STAT", kAddCRLF);
  198.         Handle hMsg= RecvUpTo( true, chLineFeed, NULL); 
  199.         //CStr255 aStr= (char*) (*hMsg);
  200.         this->ShowMessage((char*) (*hMsg));  
  201.         DisposeIfHandle( RecvChars( CharsAvailable()));
  202.         if (**hMsg == '+') {
  203.             char *cp = *hMsg + 3; // skip 3 chars
  204.             //fMsgCount= atol( cp);
  205.             char *cend= strchr(*hMsg, 0);
  206.             while (cp < cend && *cp == ' ') cp++;
  207.             while (cp < cend && *cp != ' ') cp++;
  208.             *cp= 0;
  209.             long aNum= 0;
  210.             stringtonum( cp, &aNum); //<< finicky...
  211.             fMsgCount= (short) aNum;
  212. #if 0
  213.             short len= aStr.Length();
  214.             short i;
  215.             for (i= 1; i<=3; i++) aStr[i]= ' ';
  216.             i= 4; 
  217.             while (i<len  && aStr[i]==' ') i++;
  218.                 //-- aNum= ORD(aStr[i]) - ORD('0'); 
  219.             while (i<len && aStr[i]!=' ') i++;
  220.             if (aStr[i]==' ') i--;
  221.             aStr[0]= i;
  222.             long aNum= 0;
  223.             StringToNum( aStr, aNum); //<< finicky...
  224.             fMsgCount= aNum;
  225. #endif
  226.             }
  227.         DisposHandle( hMsg);
  228.         }
  229. }
  230.  
  231.  
  232. short TPOP::NumberOfMessages()
  233. {
  234.     if (fPOPState == kPOPtransaction) return fMsgCount;
  235.     else return 0;
  236. }
  237.  
  238.  
  239. Handle TPOP::ReadMail(short msgNum, Boolean andDelete)
  240. {
  241.     CStr255  sNum; 
  242.     Handle        hMsg;
  243.  
  244.     if (fPOPState == kPOPtransaction) {
  245.         NumToString( msgNum, sNum);
  246.         SendStr( "RETR " + sNum, kAddCRLF);
  247.         hMsg= RecvMsg( '+', FreeMem() / 2);
  248.         this->ShowMessage( (char*) (*hMsg));
  249.         if ( hMsg == NULL || **hMsg == '•') 
  250.             return NULL;  
  251.         else {
  252.             if (andDelete) DeleteMail( msgNum);
  253.             return hMsg;
  254.             }
  255.         }    
  256.     else
  257.         return NULL;
  258. }
  259.  
  260.  
  261.  
  262. void DropTail( short keeplines, char endLine, short maxEndline, Handle h)
  263. {  
  264.     short        n = 0, linewidth; 
  265.     long        i, hlen;
  266.     char        *buf;
  267.     Boolean        pastHeader = false;
  268.  
  269.     hlen= GetHandleSize(h);
  270.     maxEndline= min( 255, maxEndline);
  271.     for (i= 1, linewidth= 0, buf= *h; 
  272.             i <= hlen; 
  273.             i++, linewidth++, buf++) {
  274.         if (*buf == endLine || linewidth > maxEndline) {
  275.             if (linewidth < 4) pastHeader= true;
  276.             if (pastHeader) n++; 
  277.             linewidth= 0;
  278.             if (n >= keeplines) {
  279.                 SetHandleSize(h, i);
  280.                 return;
  281.                 }
  282.             }
  283.         } 
  284.  
  285. Handle TPOP::ReadTop(short msgNum, short nLines)
  286. {
  287.     CStr255    sNum, sNum2;
  288.     Handle        hMsg;
  289.  
  290.      if (fPOPState == kPOPtransaction) {
  291.         NumToString( msgNum, sNum);
  292.         NumToString( nLines, sNum2);
  293.         SendStr( "TOP " + sNum + " " + sNum2, kAddCRLF);
  294.         hMsg= RecvMsg('+', FreeMem()/2);
  295.         this->ShowMessage( (char*) (*hMsg));
  296.         if (hMsg==NULL || **hMsg == '•') {
  297.             //'TOP' is Optional POP3 msg, try .ReadMail and cut to nLines...
  298.             hMsg= ReadMail( msgNum, false);
  299.             if (hMsg!=NULL) DropTail( nLines, chRtn, 255, hMsg);
  300.             return hMsg; 
  301.             }        
  302.         else 
  303.             return hMsg;
  304.         }    
  305.     else
  306.         return NULL;
  307. }
  308.  
  309.  
  310.  
  311. void TPOP::DeleteMail(short msgNum)
  312. {
  313.     CStr255    sNum;
  314.     Handle        hMsg;
  315.     if (fPOPState == kPOPtransaction) {
  316.         NumToString(msgNum, sNum);
  317.         SendStr( "DELE "+sNum, kAddCRLF);
  318.         hMsg= RecvUpTo( true, chLineFeed, NULL);
  319.         this->ShowMessage( (char*) (*hMsg));
  320.         if (hMsg!=NULL && **hMsg == '+')  ;
  321.         DisposeIfHandle( hMsg);
  322.         DisposeIfHandle( RecvChars( CharsAvailable()));
  323.         }
  324. }
  325.  
  326.  
  327. void TPOP::UnDeleteMail()
  328. {
  329.     Handle    hMsg;
  330.     if (fPOPState == kPOPtransaction) {
  331.         SendStr("RSET",kAddCRLF);
  332.             //count isn't changed by delete/undel >> GetMessageCount; 
  333.         hMsg= RecvUpTo( true, chLineFeed, NULL);
  334.         this->ShowMessage((char*) (*hMsg));
  335.         if (hMsg!=NULL  && **hMsg == '+') ;
  336.         DisposeIfHandle( hMsg);
  337.         DisposeIfHandle( RecvChars( CharsAvailable()));
  338.         }    
  339. }
  340.  
  341.  
  342.  
  343. Boolean TPOP::MailWaiting()
  344. /*general purpose checker:  
  345.     if connection == closed, reopen...
  346.     if mail waiting, return yes && leave open
  347.     if no mail, close connection
  348. ---*/
  349. {
  350.     Boolean        gotsome;
  351.     if (fPOPState != kPOPtransaction || Status() != kTCPestablished)
  352.             ReOpen();
  353.     gotsome= NumberOfMessages() > 0; 
  354.     if (!gotsome) Release();
  355.   this->ShowMessage( StatusString(Status()) ); 
  356.     return gotsome;
  357. }